﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Linq;

namespace ClearbrookStudios.Controls
{
    public class PanningTile : ContentControl
    {
        // TODO Add ZoomIn, ZoomOut effects
        // TODO Watermarked marquee text property/text style/text size
        // TODO Watermarked text animation length property

        private Canvas canvas;
        private Storyboard storyBoard;
        private RectangleGeometry clipper;
        private Image image;

        public int AnimationLength { get; set; }

        public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register(
            "ImageSource", 
            typeof(ImageSource), 
            typeof(PanningTile), 
            null
            );

        public ImageSource ImageSource
        {
            get
            {
                return base.GetValue(ImageSourceProperty) as ImageSource;
            }
            set
            {
                base.SetValue(ImageSourceProperty, value);
            }
        }

        public static readonly DependencyProperty PanDirectionProperty = DependencyProperty.Register(
            "PanDirection",
            typeof(PanDirection),
            typeof(PanningTile),
            new PropertyMetadata(PanDirection.Random)
            );

        public PanDirection PanDirection
        {
            get
            {
                return (PanDirection)GetValue(PanDirectionProperty);
            }
            set
            {
                base.SetValue(PanDirectionProperty, value);
            }
        }

        public static readonly DependencyProperty SizeProperty = DependencyProperty.Register(
            "Size",
            typeof(double),
            typeof(PanningTile),
            new PropertyMetadata((double)-1, OnSizeChanged)
            );

        public double Size
        {
            get
            {
                // TODO Ensure that height/width are the same
                return (double)GetValue(HeightProperty);
            }
            set
            {
                base.SetValue(WidthProperty, value);
                base.SetValue(HeightProperty, value);
            }
        }

        private static void OnSizeChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            PanningTile tile = target as PanningTile;
            tile.Height = (double)e.NewValue;
            tile.Width = (double)e.NewValue;
        }
        
        public PanningTile()    
        {        
            DefaultStyleKey = typeof(PanningTile);
            Loaded += PanningTile_Loaded;
        }     
        
        private void PanningTile_Loaded (object sender, RoutedEventArgs e)
        {
            
            ClipImage();

            storyBoard = GetPanningStoryboard();
            SetImageOffset(storyBoard);
            SetStoryboardLength(storyBoard);
            storyBoard.Begin();
        }

        private void SetImageOffset(Storyboard story)
        {
            image = GetTemplateChild("TileImage") as Image;
            double width = image.ActualHeight;
            double offset = Size - width;

            foreach (DoubleAnimationUsingKeyFrames animation in story.Children)
            {
                foreach (EasingDoubleKeyFrame keyframe in animation.KeyFrames)
                {
                    if (PanDirection != PanDirection.ZoomIn && PanDirection != PanDirection.ZoomOut)
                    {
                        if (keyframe.Value != 0)
                        {
                            keyframe.Value = offset;
                        }
                    }
                    else
                    {
                        double ratio = Size / width;
                        if (keyframe.Value != 1)
                        {
                            keyframe.Value = ratio;
                        }
                    }
                }
            }
        }

        private void ClipImage()
        {
            canvas = GetTemplateChild("PanningCanvas") as Canvas;
            clipper = new RectangleGeometry();
            int margin = 0;
            clipper.Rect = new Rect(margin, margin, Size, Size);
            canvas.Clip = clipper;
        }

        private Storyboard GetPanningStoryboard()
        {
            Storyboard pan;

            if (PanDirection == PanDirection.Random)
            {
                pan = SetRandomPanDirection();
            }
            else
            {
                pan = GetTemplateChild(PanDirection.ToString()) as Storyboard;
            }
            return pan;
        }

        private Storyboard SetRandomPanDirection()
        {
            Storyboard pan;
            int randomIndex = GetRandomIndex();
            string direction = ((PanDirection)randomIndex).ToString();
            pan = GetTemplateChild(direction) as Storyboard;
            return pan;
        }

        private int GetRandomIndex()
        {
            Random randomGenerator = new Random();
            int min = 1;
            int max = EnumHelper.Count(typeof(PanDirection));
            return randomGenerator.Next(min, max);
        }

        private void SetStoryboardLength(Storyboard storyBoard)
        {
            int finalKeyFrameIndex = 1;
            foreach (var animation in storyBoard.Children)
            {
                DoubleAnimationUsingKeyFrames ani = (DoubleAnimationUsingKeyFrames)animation;
                EasingDoubleKeyFrame endingKeyFrame = ani.KeyFrames[finalKeyFrameIndex] as EasingDoubleKeyFrame;
                endingKeyFrame.KeyTime = TimeSpan.FromSeconds(AnimationLength);
            }
        }
    }
}
